package com.luo.d3s.anti.mvc.ec.service.impl;

import com.luo.d3s.anti.mvc.ec.dao.GoodsTagBindingMapper;
import com.luo.d3s.anti.mvc.ec.dao.GoodsTagMapper;
import com.luo.d3s.anti.mvc.ec.model.dto.GoodsTagCreateDto;
import com.luo.d3s.anti.mvc.ec.model.dto.GoodsTagModifyDto;
import com.luo.d3s.anti.mvc.ec.model.dto.GoodsTagPageQueryDto;
import com.luo.d3s.anti.mvc.ec.entity.GoodsTag;
import com.luo.d3s.anti.mvc.ec.service.GoodsTagService;
import com.luo.d3s.anti.mvc.ec.model.vo.GoodsTagVo;
import com.luo.d3s.core.application.assmebler.BaseAssembler;
import com.luo.d3s.core.application.assmebler.PageResponseAssembler;
import com.luo.d3s.core.application.dto.PageResponse;
import com.luo.d3s.core.application.dto.Response;
import com.luo.d3s.core.application.dto.SingleResponse;
import com.luo.d3s.core.util.validation.Validates;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Collections;
import java.util.Objects;

/**
 * 商品标签命令处理服务实现类
 *
 * @author luohq
 * @date 2023-08-03
 */
@Service
public class GoodsTagServiceImpl implements GoodsTagService {

    @Resource
    private GoodsTagMapper goodsTagMapper;

    @Resource
    private GoodsTagBindingMapper goodsTagBindingMapper;

    @Override
    public SingleResponse<GoodsTagVo> findGoodsTag(Long goodsTagId) {
        GoodsTag goodsTag = this.goodsTagMapper.selectById(goodsTagId);
        return SingleResponse.of(BaseAssembler.convert(goodsTag, GoodsTagVo.class));
    }

    @Override
    public PageResponse<GoodsTagVo> findGoodsTagPage(GoodsTagPageQueryDto goodsTagPageQueryDto) {
        PageResponse<GoodsTag> pageResp = this.goodsTagMapper.findPage(goodsTagPageQueryDto);
        return PageResponseAssembler.toPageResp(pageResp, goodsTag -> BaseAssembler.convert(goodsTag, GoodsTagVo.class));
    }

    @Transactional(rollbackFor = Throwable.class)
    @Override
    public SingleResponse<GoodsTagVo> createGoodsTag(GoodsTagCreateDto goodsTagCreateDto) {
        //创建商品标签实体
        GoodsTag goodsTag = BaseAssembler.convert(goodsTagCreateDto, GoodsTag.class);
        //验证新增商品标签是否合法
        this.validateTagNameUnique(goodsTag);
        //保存商品标签
        this.goodsTagMapper.insert(goodsTag);
        //转换GoodsTagVo
        return SingleResponse.of(BaseAssembler.convert(goodsTag, GoodsTagVo.class));
    }

    @Transactional(rollbackFor = Throwable.class)
    @Override
    public Response modifyGoodsTag(GoodsTagModifyDto goodsTagModifyDto) {
        //验证标签是否存在
        GoodsTag existGoodsTag = this.goodsTagMapper.selectById(goodsTagModifyDto.getId());
        Validates.notNull(existGoodsTag, "goodsTag does not exist");
        //修改基础信息
        GoodsTag goodsTag = BaseAssembler.convert(goodsTagModifyDto, GoodsTag.class);
        //验证待修改商品标签是否合法
        this.validateTagNameUnique(goodsTag);
        //保存实体
        this.goodsTagMapper.updateById(goodsTag);
        return Response.buildSuccess();
    }

    @Transactional(rollbackFor = Throwable.class)
    @Override
    public Response removeGoodsTag(Long goodsTagId) {
        //验证待删除的商品标签ID下不存在商品
        Boolean existGoods = this.goodsTagBindingMapper.existByTagIds(Collections.singletonList(goodsTagId));
        Validates.isFalse(existGoods, "exist goods in tags");


        //批量删除当前商品标签及其子商品标签
        this.goodsTagMapper.deleteById(goodsTagId);
        return Response.buildSuccess();
    }

    /**
     * 验证标签名称唯一性
     *
     * @param goodsTag 商品标签对象
     */
    private void validateTagNameUnique(GoodsTag goodsTag) {
        //验证商品标签名称唯一性
        GoodsTag existGoodsTag = this.goodsTagMapper.findByTagName(goodsTag.getTagName());
        //是否存在标签名（标签名不存在 或者 存在的标签名不是当前记录）
        Boolean existGoodsTagName = Objects.nonNull(existGoodsTag) && !existGoodsTag.getId().equals(goodsTag.getId());
        Validates.isFalse(existGoodsTagName, "goodsTag tagName is repeated");
    }
}
